import { Component, OnInit, Input, Output, EventEmitter, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

interface checkKeyObjs {
  key: number | string,
  label: number | string
}

@Component({
  selector: 'zdy-checkbox-group',
  templateUrl: './checkbox-group.component.html',
  styleUrls: ['./checkbox-group.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CheckboxGroupComponent),
      multi: true
    }
  ]
})
export class CheckboxGroupComponent implements ControlValueAccessor, OnInit {

  @Input() checkOptions!: Array<any>;
  @Input() checkKeys: checkKeyObjs = {key: 'value', label: 'label'};
  @Input() resToStr: boolean = false;
  @Input() disabled: boolean = false;
  @Input() isAllCheck: boolean = true;
  @Output() singCheckedChange = new EventEmitter();

  allChecked = false;
  notAllChecked = false;
  indeterminate = false;
  _onChange: any = () => {};

  constructor() { }

  ngOnInit(): void {
    
  }

  // 全选
  updateAllChecked(): void {
    this.indeterminate = false;

    if (this.allChecked) {
      this.notAllChecked = false;
      this.checkOptions = this.checkOptions.map(item => ({
        ...item,
        checked: true
      }));
    } else {
      this.checkOptions = this.checkOptions.map(item => ({
        ...item,
        checked: false
      }));
    }
    this.retunResult();
  }

  // 全不选(后加)
  updateNotAllChecked() {
    this.indeterminate = false;
    this.allChecked = false;
    this.notAllChecked = true;

    this.checkOptions = this.checkOptions.map(item => ({
      ...item,
      checked: false
    }));
    this.retunResult();
  }

  // 单选
  updateSingleChecked(result: any) {
    if (this.checkOptions.every(item => !item.checked)) {
      this.allChecked = false;
      this.indeterminate = false;
    } else if (this.checkOptions.every(item => item.checked)) {
      this.allChecked = true;
      this.indeterminate = false;
    } else {
      this.allChecked = false;
      this.indeterminate = true;
    }
    
    this.notAllChecked = false;
    this.retunResult();
    this.singCheckedChange.emit();
  }

  retunResult() {
    let arr = this.checkOptions.filter((tag: any) => tag.checked).map(((m: any) => m.value));
    this._onChange(this.resToStr ? arr.join(',') : arr);
  }

  /**
   * ----------------------------------------------------------------
   * ngModel Change
   * ----------------------------------------------------------------
   */
  writeValue(value: any): void {
    let valType = Object.prototype.toString.call(value);
    if (['[object Array]', '[object String]'].includes(valType)) {
      this.checkOptions.forEach((item: any) => {
        item.value = item[this.checkKeys['key']];
        item.label = item[this.checkKeys['label']];

        if (value.includes(item[this.checkKeys['key']])) {
          item.checked = true;
        } else {
          item.checked = false;
        }
      })

      let tempArrs = valType === '[object Array]' ? value : (value ? value.split(',') : []);
      this.allChecked = tempArrs.length === this.checkOptions.length ? true : false;
      if (tempArrs.length > 0 && tempArrs.length < this.checkOptions.length) {
        this.indeterminate = true;
      } else {
        this.indeterminate = false;
      }
    }
  }

  registerOnChange(fn: (_: any) => void): void {
    this._onChange = fn;
  }

  registerOnTouched(fn: any): void {}
}
